﻿#include "BluetoothDeviceModel.h"
#include <QDebug>


BluetoothDeviceModel *BluetoothDeviceModel::Singleton()
{
    static BluetoothDeviceModel * singleton = new BluetoothDeviceModel();
    return singleton;
}

BluetoothDeviceModel::BluetoothDeviceModel(QObject *parent ) : QAbstractListModel(parent)
{
#if 0
    addDevice("HC-06", "20:00:15:25::65:56", 0, false, false, QBluetoothDeviceInfo());
    addService("Serial Port Profile", 2, "{00001101-0000-1000-8000-00805f9b34fb}", QBluetoothServiceInfo(), "HC-06", "20:00:15:25::65:56", QBluetoothDeviceInfo());
    addDevice("HC-05", "20:00:15:25::34:87", 0, false, false, QBluetoothDeviceInfo());
    addService("Serial Port Profile", 2, "{00001101-0000-1000-8000-00805f9b34fb}", QBluetoothServiceInfo(), "HC-05" , "20:00:15:25::34:87", QBluetoothDeviceInfo());
    addService("未知", 2, "{00001101-0000-1000-8000-00805ddd34fb}", QBluetoothServiceInfo(), "HC-05" , "20:00:15:25::34:87", QBluetoothDeviceInfo());
    addDevice("HC-08", "00:15:87:21:0F:1D", 0, true, false, QBluetoothDeviceInfo());
#endif
}

int BluetoothDeviceModel::rowCount(const QModelIndex &) const
{
    return mBluetoothInfoList.count();
}

QVariant BluetoothDeviceModel::data(const QModelIndex &index, int role) const
{
    if (index.row() < rowCount())
    {
        switch (role) {
        case ServiceNameRole: return mBluetoothInfoList.at(index.row()).serviceName;
        case SocketProtocolRole: return mBluetoothInfoList.at(index.row()).socketProtocol;
        case ServiceClassUuidRole: return mBluetoothInfoList.at(index.row()).serviceClassUuid;
        case DeviceNameRole: return mBluetoothInfoList.at(index.row()).deviceName;
        case DeviceAddrRole: return mBluetoothInfoList.at(index.row()).deviceAddr;
        case SectionInfoRole: return mBluetoothInfoList.at(index.row()).sectionInfo;
        case RowTypeRole: return mBluetoothInfoList.at(index.row()).rowType;
        case RssiRole: return mBluetoothInfoList.at(index.row()).rssi;
        case IsLowEnergyRole: return mBluetoothInfoList.at(index.row()).isLowEnergy;
        case IsPairedRole: return mBluetoothInfoList.at(index.row()).isPaired;
        case IsSocketConnectedRole: return mBluetoothInfoList.at(index.row()).isSocketConnected;
        case childItemCountRole: return mBluetoothInfoList.at(index.row()).childItemCount;

        default: return QVariant();
        }
    }
    return QVariant();
}

QHash<int, QByteArray> BluetoothDeviceModel::roleNames() const
{
    static const QHash<int, QByteArray> roles {
        { ServiceNameRole, "serviceName" },
        { SocketProtocolRole, "socketProtocol" },
        { ServiceClassUuidRole, "serviceClassUuid" },
        { DeviceNameRole, "deviceName" },
        { DeviceAddrRole, "deviceAddr" },
        { SectionInfoRole, "sectionInfo" },
        { RowTypeRole, "rowType" },
        { RssiRole, "rssi" },
        { IsLowEnergyRole, "isLowEnergy" },
        { IsPairedRole, "isPaired" },
        { IsSocketConnectedRole, "isSocketConnected" },
        { childItemCountRole, "childItemCount" },
    };
    return roles;
}

QString BluetoothDeviceModel::toSectinInfo(const QString &deviceName, const QString &deviceAddr)
{
    Q_UNUSED(deviceName)
    Q_UNUSED(deviceAddr)
    //<font color="color_name" size="1-7"></font>
    //return tr("%1<br/><font size=\"8\" color=\"gray\">%2</font>").arg(deviceName).arg(deviceAddr);
    return deviceAddr;
}

QVariantMap BluetoothDeviceModel::get(int row) const
{
    const BluetoothDevice bluetoothDevice = mBluetoothInfoList.value(row);
    return { {"serviceName", bluetoothDevice.serviceName}
        , {"socketProtocol", bluetoothDevice.socketProtocol}
        , {"serviceClassUuid", bluetoothDevice.serviceClassUuid}
        , {"deviceName", bluetoothDevice.deviceName}
        , {"deviceAddr", bluetoothDevice.deviceAddr}
        , {"sectionInfo", bluetoothDevice.sectionInfo}
        , {"rowType", bluetoothDevice.rowType}
        , {"childItemCount", bluetoothDevice.childItemCount }
    };
}

void BluetoothDeviceModel::addService(const QString& serviceName, const int socketProtocol, const QString& serviceClassUuid, QBluetoothServiceInfo serviceInfo
                                      , const QString& deviceName, const QString& deviceAddr, QBluetoothDeviceInfo deviceInfo)
{
    //QString sectionInfo = toSectinInfo(deviceName, deviceAddr);
    int deviceRow = -1;
    for (int row = 0; row < mBluetoothInfoList.count(); ++row)
    {
        if(EnumRowType_Device == mBluetoothInfoList.at(row).rowType
                && deviceAddr == mBluetoothInfoList.at(row).deviceAddr)
        {
            deviceRow = row;
            if(deviceName != mBluetoothInfoList.at(row).deviceName)
            {
                mBluetoothInfoList[row].deviceName = deviceName;
                dataChanged(index(row, 0), index(row, 0), {DeviceNameRole});
                qDebug() << "row:" << row << "deviceName changed:" << deviceName;
            }
        }
        if(EnumRowType_Service == mBluetoothInfoList.at(row).rowType
                && serviceName == mBluetoothInfoList.at(row).serviceName
                && socketProtocol == mBluetoothInfoList.at(row).socketProtocol
                && serviceClassUuid == mBluetoothInfoList.at(row).serviceClassUuid
                //&& deviceName == mBluetoothInfoList.at(row).deviceName
                && deviceAddr == mBluetoothInfoList.at(row).deviceAddr
                )
        {
            if(deviceName != mBluetoothInfoList.at(row).deviceName)
            {
                mBluetoothInfoList[row].deviceName = deviceName;
                qDebug() << "row:" << row << "deviceName changed:" << deviceName;
            }
            return ;
        }
    }

    if(-1 == deviceRow)
    {// 没添加设备,还需要先添加设备
        int row = mBluetoothInfoList.size();
        beginInsertRows(QModelIndex(), row, row);
        mBluetoothInfoList.insert(row, BluetoothDevice(deviceName, deviceAddr, 0, false, false, deviceInfo));
        mBluetoothInfoList.insert(row+1, BluetoothDevice(serviceName, socketProtocol, serviceClassUuid, serviceInfo, deviceName, deviceAddr, deviceInfo));
        endInsertRows();
        // 子项数加1
        mBluetoothInfoList[row].childItemCount++;
        dataChanged(index(row, 0), index(row, 0), {childItemCountRole});
    }
    else
    {
        // 找到蓝牙设备索引
        int row = deviceRow + 1;
        for (; row < mBluetoothInfoList.size(); ++row)
        {
            if(mBluetoothInfoList.at(row).rowType < EnumRowType_Service)
            {// 已经是下一个组
                break;
            }
            if(mBluetoothInfoList.at(row).rowType > EnumRowType_Service)
            {// 更内部的分组
                continue;
            }
            if(serviceClassUuid > mBluetoothInfoList.at(row).serviceClassUuid)
            {
                continue;
            }
            else
            {
                break;
            }
        }
        beginInsertRows(QModelIndex(), row, row);
        mBluetoothInfoList.insert(row, BluetoothDevice(serviceName, socketProtocol, serviceClassUuid, serviceInfo, deviceName, deviceAddr, deviceInfo));
        endInsertRows();
        // 子项数加1
        mBluetoothInfoList[deviceRow].childItemCount++;
        dataChanged(index(deviceRow, 0), index(deviceRow, 0), {childItemCountRole});
    }
}

void BluetoothDeviceModel::addDevice(const QString &deviceName, const QString &deviceAddr, int rssi, bool isLowEnergy, bool isPaired, QBluetoothDeviceInfo deviceInfo)
{
    //QString sectionInfo = toSectinInfo(deviceName, deviceAddr);
    for (int row = 0; row < mBluetoothInfoList.count(); ++row)
    {
        if(EnumRowType_Device == mBluetoothInfoList.at(row).rowType
                && deviceAddr == mBluetoothInfoList.at(row).deviceAddr
                )
        {// 已存在
            if(deviceName != mBluetoothInfoList.at(row).deviceName)
            {
                mBluetoothInfoList[row].deviceName = deviceName;
                dataChanged(index(row, 0), index(row, 0), {DeviceNameRole});
                qDebug() << "row:" << row << "deviceName changed:" << deviceName;
            }
            return ;
        }
    }

    int row = 0;
    while (row < mBluetoothInfoList.count())
    {
        if(mBluetoothInfoList.at(row).rowType < EnumRowType_Device)
        {// 已经是下一个组
            break;
        }
        if(mBluetoothInfoList.at(row).rowType > EnumRowType_Device)
        {// 更内部的分组
            continue;
        }

        if(deviceAddr > mBluetoothInfoList.at(row).deviceAddr)
        {
            ++row;
            continue;
        }
        else
        {
            break;
        }
    }
    beginInsertRows(QModelIndex(), row, row);
    mBluetoothInfoList.insert(row, BluetoothDevice(deviceName, deviceAddr, rssi, isLowEnergy, isPaired, deviceInfo));
    endInsertRows();
}

void BluetoothDeviceModel::updateDeviceName(const QString &deviceName, const QString &deviceAddr)
{
    for (int row = 0; row < mBluetoothInfoList.count(); ++row)
    {
        if(EnumRowType_Device == mBluetoothInfoList.at(row).rowType
                && deviceAddr == mBluetoothInfoList.at(row).deviceAddr
                )
        {
            mBluetoothInfoList[row].deviceName = deviceName;
            dataChanged(index(row, 0), index(row, 0), {DeviceNameRole});
            return ;
        }
    }
}

void BluetoothDeviceModel::updateRssi(const QString &deviceAddr, int rssi)
{
    for (int row = 0; row < mBluetoothInfoList.count(); ++row)
    {
        if(EnumRowType_Device == mBluetoothInfoList.at(row).rowType
                && deviceAddr == mBluetoothInfoList.at(row).deviceAddr
                )
        {
            mBluetoothInfoList[row].rssi = rssi;
            dataChanged(index(row, 0), index(row, 0), {RssiRole});
            return ;
        }
    }
}

void BluetoothDeviceModel::updateSocketConnectState(const QString &deviceAddr, const QString& serviceClassUuid, bool isSocketConnected)
{
    for (int row = 0; row < mBluetoothInfoList.count(); ++row)
    {
        if(EnumRowType_Service == mBluetoothInfoList.at(row).rowType
                && deviceAddr == mBluetoothInfoList.at(row).deviceAddr
                && serviceClassUuid == mBluetoothInfoList.at(row).serviceClassUuid
                )
        {
            mBluetoothInfoList[row].isSocketConnected = isSocketConnected;
            dataChanged(index(row, 0), index(row, 0), {IsSocketConnectedRole});
            return ;
        }
    }
}

void BluetoothDeviceModel::remove(int row)
{
    if (row < 0 || row >= mBluetoothInfoList.count())
    {
        return;
    }
    EnumRowType rowType = mBluetoothInfoList.at(row).rowType;
    beginRemoveRows(QModelIndex(), row, row);
    mBluetoothInfoList.removeAt(row);
    endRemoveRows();

    //
    if(rowType == BluetoothDeviceModel::EnumRowType_Service)
    {
        for(int i = row - 1; i >= 0; --i)
        {
            if(rowType - mBluetoothInfoList.at(i).rowType == 1)
            {
                // 子项数-1
                if(mBluetoothInfoList[i].childItemCount > 0)
                {
                    mBluetoothInfoList[i].childItemCount--;
                    dataChanged(index(i, 0), index(i, 0), {childItemCountRole});
                }
                break;
            }
        }
    }
}

void BluetoothDeviceModel::clear()
{
    int count = mBluetoothInfoList.count();
    if(count > 0)
    {
        beginRemoveRows(QModelIndex(), 0, count-1);
        mBluetoothInfoList.clear();
        endRemoveRows();
    }
}

